//
//  CJPNimble.swift
//  CJPack
//
//  Created by 陈警卫 on 2023-07-12.
//

import UIKit
import Foundation

enum CJPPanLocation {
    case unknown
    case left
    case right
}

enum CJPPanDire {
    case unknown
    case vertical
    case horizontal
}

enum CJPMoveDire {
    case unknown
    case left
    case right
    case top
    case bottom
}

class CJPNimble: NSObject {
    
    var didSingleTap: ((CJPNimble) -> ())?
    var didDoubleTap: ((CJPNimble) -> ())?
    
    var didPanGR: ((CJPNimble) -> ())?
    var didPanBegan: ((CJPNimble) -> ())?
    var didPanChanged: ((CJPNimble, CGPoint) -> ())?
    var didPanEnded: ((CJPNimble) -> ())?
    
    /// 平移位置
    var panLocation: CJPPanLocation = .unknown
    /// 平移轴向
    var panDire: CJPPanDire = .unknown
    /// 平移方向
    var moveDire: CJPMoveDire = .unknown
    
    weak var controlView: UIView!
    
    lazy var singleTap: UITapGestureRecognizer = {
        let singleTap = UITapGestureRecognizer(target: self, action: #selector(singleTapAction(gr:)))
        singleTap.delegate = self
        singleTap.delaysTouchesBegan = true
        singleTap.delaysTouchesEnded = true
        singleTap.numberOfTouchesRequired = 1
        singleTap.numberOfTapsRequired = 1
        return singleTap
    }()
    
    lazy var doubleTap: UITapGestureRecognizer = {
        let doubleTap = UITapGestureRecognizer(target: self, action: #selector(doubleTapAction(gr:)))
        doubleTap.delegate = self
        doubleTap.delaysTouchesBegan = true
        doubleTap.delaysTouchesEnded = true
        doubleTap.numberOfTouchesRequired = 1
        doubleTap.numberOfTapsRequired = 2
        return doubleTap
    }()
    
    lazy var panGR: UIPanGestureRecognizer = {
        let panGR = UIPanGestureRecognizer(target: self, action: #selector(panGRAction(gr:)))
        panGR.delegate = self
        panGR.delaysTouchesBegan = true
        panGR.delaysTouchesEnded = true
        panGR.maximumNumberOfTouches = 1
        panGR.cancelsTouchesInView = true
        return panGR
    }()
    
}

extension CJPNimble {
    
    func setupGesture(_ view: UIView) {
        controlView = view
        
        singleTap.require(toFail: doubleTap)
        singleTap.require(toFail: panGR)
        
        controlView.addGestureRecognizer(singleTap)
        controlView.addGestureRecognizer(doubleTap)
        controlView.addGestureRecognizer(panGR)
    }
    
    func removeGesture(_ view: UIView) {
        view.removeGestureRecognizer(singleTap)
        view.removeGestureRecognizer(doubleTap)
        view.removeGestureRecognizer(panGR)
    }
}

extension CJPNimble {
    
    @objc func singleTapAction(gr: UITapGestureRecognizer) {
        if let didSingleTap = didSingleTap {
            didSingleTap(self)
        }
    }
    
    @objc func doubleTapAction(gr: UITapGestureRecognizer) {
        if let didDoubleTap = didDoubleTap {
            didDoubleTap(self)
        }
    }
    
    @objc func panGRAction(gr: UIPanGestureRecognizer) {
        let translate = gr.translation(in: gr.view)
        let velocity = gr.velocity(in: gr.view)
        
        if gr.state == .began {
            panDire = .unknown
            let x = abs(velocity.x)
            let y = abs(velocity.y)
            if x > y {
                panDire = .horizontal
            } else if x < y {
                panDire = .vertical
            } else {
                panDire = .unknown
            }
            if let didPanBegan = didPanBegan {
                didPanBegan(self)
            }
        } else if gr.state == .changed {
            if panDire == .horizontal {
                if translate.x > 0 {
                    moveDire = .right
                } else {
                    moveDire = .left
                }
            } else if panDire == .vertical {
                if translate.y > 0 {
                    moveDire = .bottom
                } else {
                    moveDire = .top
                }
            }
            if let didPanChanged = didPanChanged {
                didPanChanged(self, velocity)
            }
        } else if gr.state == .ended {
            if let didPanEnded = didPanEnded {
                didPanEnded(self)
            }
        }
        gr.setTranslation(.zero, in: gr.view)
    }
}

extension CJPNimble: UIGestureRecognizerDelegate {
    
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if gestureRecognizer == panGR {
            let locationPoint = touch.location(in: touch.view)
            if locationPoint.x > controlView.bounds.size.width/2.0 {
                panLocation = .right
            } else {
                panLocation = .left
            }
        }
        return true
    }
    
}
